from spConstants import *
from time import sleep, clock
import serial


########################################################################
class SmallProtocol:
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        # Start the serial port
        self.ser = serial.Serial('COM4',115200,timeout=0)

    def __receive_decode(self, data=False):
        """
        
        
        """
        receivedBuffer = bytearray()
        count = 0 # bytes counter
        startTime = clock()
        ret = False;
        while(True):
            #Timeout of 3 second;
            if(clock()>startTime+300):
                ret = False;
                break;
            c = self.ser.read()

            if(c!=""):
                count+=1
                if(not data):
                    if((ord(c)==ACK) and (count==1)):
                        ret = True 
                        break
                    elif((ord(c)==NAK) and count==1):
                        ret = False;
                        break                

                else: # Receive ACK first and then data   

                    if((ord(c)==ACK) and (count==1)):
                        ret = True;
                        #sleep(1)
                        continue
                        # ready to receive data
                    elif((ord(c)==NAK) and count==1):
                        ret = False;
                        break

                    receivedBuffer.append(c)
                    if((count>3) and (count-4==receivedBuffer[1])):
                        #print receivedBuffer
                        #received all data, exit
                        break

        return ret, receivedBuffer;

    def __calcCRC(self, buffer):
        bcc = 0
        for i in buffer:
            bcc = bcc + i
        bcc = bcc % 256	
        return bcc

    def __CRC_Check(self, buffer):
        """
        """
        bcc = self.__calcCRC(buffer[:len(buffer)-1])
        ret = bcc == buffer[len(buffer)-1]
        return ret

    def __send(self, buffer, protocol=False):

        """
          Input:		buffer, protocol
          Output:		---
          Description:    Sends data to display, adding protocol:
                          DC1/DC2 | length | data..... | bcc
                          <DC1> = 17(dec.) = 0x11 <DC2> = 18(dec.) = 0x12 
                          length = count of user data (without <DC1/DC2>, without checksum bcc)
                          bcc = 1 byte = sum of all bytes incl. <DC1/DC2> and len, modulo 256
                          sends array, using uart_send(), lenght = data amount to be send
                          protocol = False (Command/Data to the display)
                          protocol = True (protocoll commands to the display)
          """

        lenbuf = len(buffer)			#length without DC and bcc	

        if(protocol):
            # protocol commands to display
            buffer.insert(0, 0x12)		#send DC2				
        else:					#Command/Data to the display
            buffer.insert(0, 0x11)		#send DC1

        buffer.insert(1, lenbuf) #send data length

        bcc = self.__calcCRC(buffer)
        buffer.append(bcc)

        return self.ser.write(buffer)
         

    def  send_Command(self, buffer, data=False, protocol=False):
        """
        sends buffer to display, takes care of the max length of bytes 
        that can be sent to the display.
        """

        if(data):
            if(len(buffer)>255):
                ack = NAK
                receivedbuffer = None
                return ack, receivedbuffer
            
            self.__send(buffer, protocol)
            ack, receivedbuffer = self.__receive_decode(data);        
            if(ack and len(receivedbuffer)>3):
                if(not self.__CRC_Check(receivedbuffer)):
                    ack = False
                else:
                    receivedbuffer = receivedbuffer[2:len(receivedbuffer)-1]
                    
            return ack, receivedbuffer                     
            
            
        while(len(buffer)!=0):
            
            #send the first 255 bytes
            if(len(buffer)>255):
                newbuffer = bytearray(buffer[0:255])
                buffer = buffer[255:]
            else:
                newbuffer = bytearray(buffer)
                buffer = bytearray()
                
            tries = 0
            while(tries<3):
                self.__send(newbuffer, protocol)
                ack, receivedbuffer = self.__receive_decode(data);
                if(ack):
                    sleep(1/100)
                    break;
                else:
                    sleep(1/100)
                    tries+=1
            
        return ack, receivedbuffer         

    